/*
 * BAT_Parser.c
 *
 * Parser for BAT.
 *
 * $Id: BAT_Parser.c 927 2006-09-03 06:17:24Z rpz $
 *
 * Bob Zimmermann <rpz@cse.wustl.edu> Totally free.
 *
 */

#include "BAT_Parser.h"
#include "BAT_Factory.h"

BAT_Parser *
BAT_Parser_new()
{
  BAT_Parser *p;

  p = malloc(sizeof(BAT_Parser));
  p->features = NULL;

  return p;
}

void
BAT_Parser_delete(BAT_Parser * p, int befrei)
{
  if (p->features != NULL)
    darray_delete(p->features, 1);
  p->features = NULL;
  if (befrei)
    free(p);
}

char *
BAT_Parser_get_filename_extension(char *filename)
{
  int i, len;
  len = strlen(filename);
  for (i = len - 1; i > 0 && filename[i] != '.'; i--);
  if (i == 0)
    return "";
  return &filename[i + 1];
}

void
BAT_Parser_parsefile_by_name(BAT_Parser * p, char *filename)
{
  FILE *file;
  da_pos_t i, sz;
  BAT_Parse_Plugin *ph;
  BAT_Parser_Type type;
  darray_t *plugins;
  BAT_Factory *fac;

  if (p->features == NULL)
    p->features =
      darray_new(100, darray_ops_copy(&BAT_Owner_Ops[Free_Feature_Allocator]));
  fac = BAT_Factory_new();
  plugins = BAT_Factory_get_parse_plugins(fac);
  sz = darray_size(plugins);
  type = BAT_Unknown_Parser_Type;
  for (i = 0; i < sz; i++) {
    ph = darray_get(plugins, i);
    if (ph->canparse(filename)) {
      if (type != BAT_Unknown_Parser_Type) {
	fprintf(stderr, "Two plugins can parse file %s.\n", filename);
	exit(1);
      }
      type = ph->type;
    }
  }
  if (type == BAT_Unknown_Parser_Type) {
    fprintf(stderr, "No plugin can parse file %s.\n", filename);
    exit(1);
  }
  BAT_Factory_delete(fac, 1);

  file = fopen(filename, "r");
  if (file == NULL) {
    fprintf(stderr, "Could not open file %s for reading.\n", filename);
    exit(1);
  }
  BAT_Parser_parsefile_by_fh(p, file, type);
  fclose(file);
}

void
BAT_Parser_parsefile_by_fh(BAT_Parser * p, FILE * fh, BAT_Parser_Type type)
{
  da_pos_t i, sz;
  BAT_Free_Feature **feats;
  BAT_Parse_Plugin *ph;
  void *parser;
  BAT_Factory *fac;

  fac = BAT_Factory_new();

  ph = BAT_Factory_get_parse_plugin(fac, type);
  parser = ph->construct();
  feats = ph->parsefile(parser, fh, &sz);
  ph->delete(parser, 1);

  BAT_Factory_delete(fac, 1);

  for (i = 0; i < sz; i++)
    darray_add(p->features, feats[i]);
  free(feats);
}

BAT_Free_Feature **
BAT_Parser_claim_features(BAT_Parser * p, unsigned *n_feats)
{
  BAT_Free_Feature **feats;
  feats = (BAT_Free_Feature **) darray_release(p->features, n_feats, 1);

  /* the caller here claims the features, we're not responsible for freeing */
  p->features = NULL;
  return feats;
}
